package com.bestcem.xm.deliver.grpc.client;

import cn.hutool.core.lang.ObjectId;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.bp.grpc.v1.base.Code;
import com.bestcem.bp.xm.user.grpc.v1.services.*;
import com.bestcem.xm.common.core.constant.GrpcClientNames;
import com.bestcem.xm.component.cache.annotation.XmCache;
import com.bestcem.xm.deliver.convert.grpc.DeliverGrpcConvertMapper;
import com.bestcem.xm.deliver.grpc.client.dto.OrgInfoDto;
import com.bestcem.xm.deliver.grpc.client.dto.UserDto;
import com.bestcem.xm.user.grpc.v1.enums.RoleTypeEnum;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

import static com.bestcem.xm.user.grpc.v1.enums.RoleTypeEnum.RoleType.SYSTEM;

@Slf4j
@Component
public class UserGrpcClient {

    @GrpcClient(GrpcClientNames.DS_USER)
    private UserServiceGrpc.UserServiceBlockingStub userServiceBlockingStub;

    @GrpcClient(GrpcClientNames.DS_USER)
    private UserGroupServiceGrpc.UserGroupServiceBlockingStub userGroupServiceBlockingStub;

    @GrpcClient(GrpcClientNames.DS_USER)
    private OrgServiceGrpc.OrgServiceBlockingStub orgServiceBlockingStub;

    @GrpcClient(GrpcClientNames.DS_USER)
    private UserRoleServiceGrpc.UserRoleServiceBlockingStub userRoleServiceBlockingStub;

    @GrpcClient(GrpcClientNames.DS_USER)
    private OrgCustomSettingServiceGrpc.OrgCustomSettingServiceBlockingStub orgCustomSettingServiceBlockingStub;

    @GrpcClient(GrpcClientNames.DS_USER)
    private SmtpServiceGrpc.SmtpServiceBlockingStub smtpServiceBlockingStub;

    private final com.bestcem.xm.deliver.convert.grpc.DeliverGrpcConvertMapper deliverGrpcConvertMapper;

    public UserGrpcClient(DeliverGrpcConvertMapper deliverGrpcConvertMapper) {
        this.deliverGrpcConvertMapper = deliverGrpcConvertMapper;
    }

    @XmCache
    public UserDto getUser(String userId) {
        GetUserByIdRequest.Builder builder = GetUserByIdRequest.newBuilder();
        builder.setId(userId);
        try {
            GetUserByIdResponse response = userServiceBlockingStub.getUserById(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[deliver] USER getUser {} Error; ErrorMsg: {}", userId, response);
                return null;
            }
            return responseToUserDTO(response);
        } catch (Exception e) {
            log.error("[deliver] USER getUser {} Error; ErrorMsg: {}", userId, e.getMessage(), e);
            return null;
        }
    }

    public List<UserDto> listUserByOrgId(String orgId) {
        ListUsersByFilterRequest.Builder builder = ListUsersByFilterRequest.newBuilder();
        UserCondition.Builder userBuilder = UserCondition.newBuilder();
        userBuilder.setOrgId(orgId);
        builder.setUser(userBuilder.buildPartial());
        try {
            ListUsersByFilterResponse response = userServiceBlockingStub.listUsersByFilter(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[deliver] USER listUserByOrgId {} Error; ErrorMsg: {}", orgId, response);
                return new ArrayList<>();
            }
            return responseToUserDTOList(response);
        } catch (Exception e) {
            log.error("[deliver] USER listUserByOrgId {} Error; ErrorMsg: {}", orgId, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    public Group getGroup(String groupId) {
        if (!ObjectId.isValid(groupId)) {
            return null;
        }
        GetGroupRequest.Builder builder = GetGroupRequest.newBuilder();
        builder.setId(groupId);
        try {
            GetGroupResponse response = userGroupServiceBlockingStub.getGroup(builder.build());
            if (Objects.isNull(response) || Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Deliver] USER getGroup {} Error; ErrorMsg: {}", groupId, response);
                return null;
            }
            return response.getGroup();
        } catch (Exception e) {
            log.error("[Deliver] USER getGroup {} Error; ErrorMsg: {}", groupId, e.getMessage(), e);
            return null;
        }
    }

    public OrgInfoDto getOrganization(String orgId) {
        GetOrgByIdOrCodeRequest.Builder builder = GetOrgByIdOrCodeRequest.newBuilder();
        builder.setId(orgId);
        try {
            GetOrgByIdOrCodeResponse response = orgServiceBlockingStub.getOrgByIdOrCode(builder.buildPartial());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[deliver] USER getOrganization {} Error; ErrorMsg: {}", orgId, response);
                return new OrgInfoDto();
            }
            /*Organization organization = response.getOrganization();
            OrgInfoDto orgInfoDTO = new OrgInfoDto();
            orgInfoDTO.setId(organization.getId());
            orgInfoDTO.setIndustryId(organization.getIndustryId());
            orgInfoDTO.setIsDeliverCheck(organization.getIsDeliverCheck());
            orgInfoDTO.setSkin(organization.getSkin());
            orgInfoDTO.setCode(organization.getCode());
            return orgInfoDTO;*/
            return deliverGrpcConvertMapper.toOrgInfoDto(response.getOrg());
        } catch (Exception e) {
            log.error("[deliver] USER getOrganization {} Error; ErrorMsg: {}", orgId, e.getMessage(), e);
            return new OrgInfoDto();
        }
    }

    public OrgInfoDto getOrganizationByIdOrCode(String orgId, String orgCode) {
        GetOrgByIdOrCodeRequest.Builder builder = GetOrgByIdOrCodeRequest.newBuilder();
        if (ObjectUtil.isNotEmpty(orgId)) {
            builder.setId(orgId);
        } else {
            builder.setCode(orgCode);
        }
        try {
            GetOrgByIdOrCodeResponse response = orgServiceBlockingStub.getOrgByIdOrCode(builder.buildPartial());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[deliver] USER getOrganization {} Error; ErrorMsg: {}", orgId, response);
                return new OrgInfoDto();
            }
            /*Organization organization = response.getOrganization();
            OrgInfoDto orgInfoDTO = new OrgInfoDto();
            orgInfoDTO.setId(organization.getId());
            orgInfoDTO.setIndustryId(organization.getIndustryId());
            orgInfoDTO.setIsDeliverCheck(organization.getIsDeliverCheck());
            orgInfoDTO.setSkin(organization.getSkin());
            orgInfoDTO.setCode(organization.getCode());
            return orgInfoDTO;*/
            return deliverGrpcConvertMapper.toOrgInfoDto(response.getOrg());
        } catch (Exception e) {
            log.error("[deliver] USER getOrganization {} Error; ErrorMsg: {}", orgId, e.getMessage(), e);
            return new OrgInfoDto();
        }
    }

    /**
     * 通过查询条件批量一次性获取所有符合条件的Role
     *
     * @param orgId    组织ID
     * @param roleName 角色名
     * @return 角色DTO集合
     * @author <yuming.pan@idiaoyan.com>
     * @date 15:07 2021/8/27
     */
    public List<Role> listRoleByOrgIdAndRoleName(String orgId, String roleName, RoleTypeEnum.RoleType roletype) {
        ListRolesRequest.Builder builder = ListRolesRequest.newBuilder();
        RoleCondition.Builder roleBuilder = RoleCondition.newBuilder();
        roleBuilder.setOrgId(orgId);
        roleBuilder.setName(roleName);
        if (roletype != null) {
            roleBuilder.setType(roletype);
        }
        builder.setRole(roleBuilder.build());
        try {
            ListRolesResponse response = userRoleServiceBlockingStub.listRoles(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[deliver] USER listRoleByOrgIdAndRoleName {},{} Error; ErrorMsg: {}", orgId, roleName, response);
                return new ArrayList<>();
            }
            return response.getRolesList();
        } catch (Exception e) {
            log.error("[deliver] USER listRoleByOrgIdAndRoleName {},{} Error; ErrorMsg: {}", orgId, roleName, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    /**
     * 获取用户角色信息
     *
     * @param userId 用户id
     * @param roleId roleId
     * @return User info
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/11/4 20:30
     */
    public List<UserRole> getUserRole(String userId, String roleId) {
        ListUserRolesRequest.Builder builder = ListUserRolesRequest.newBuilder();
        if (userId != null) {
            builder.setUserId(userId);
        }
        builder.setRoleId(roleId);
        try {
            ListUserRolesResponse response = userServiceBlockingStub.listUserRoles(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[deliver] USER getUser {} Error; ErrorMsg: {}", userId, response);
                return new ArrayList<>();
            }
            return response.getRolesList();
        } catch (Exception e) {
            log.error("[deliver] USER getUser {} Error; ErrorMsg: {}", userId, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    /**
     * 获取高级管理员
     *
     * @param orgId orgId
     * @return User info
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/11/4 20:30
     */
    public List<String> getSeniorAdminIdByOrgId(String orgId) {
        ListSeniorAdminIdsRequest.Builder builder = ListSeniorAdminIdsRequest.newBuilder();
        builder.setOrgId(orgId);
        try {
            ListSeniorAdminIdsResponse response = userServiceBlockingStub.listSeniorAdminIds(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[deliver] GetSeniorAdminIdByOrgId orgId {} Error; ErrorMsg: {}", orgId, response);
                return new ArrayList<>();
            }
            return response.getIdsList();
        } catch (Exception e) {
            log.error("[deliver] GetSeniorAdminIdByOrgId orgId {} Error; e : ", orgId, e);
            return new ArrayList<>();
        }
    }

    /**
     * 获取管理员
     *
     * @param orgId orgId
     * @return User info
     * @author XiaoYunSong <ys.xiao@idiaoyan.cn>
     * @date 2021/11/4 20:30
     */
    public List<String> listOrgAdminIds(String orgId) {
        ListAdminIdsRequest.Builder builder = ListAdminIdsRequest.newBuilder();
        builder.setOrgId(orgId);
        try {
            ListAdminIdsResponse response = userServiceBlockingStub.listAdminIds(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[deliver] listOrgAdminIds orgId {} Error; ErrorMsg: {}", orgId, response);
                return new ArrayList<>();
            }
            return response.getIdsList();
        } catch (Exception e) {
            log.error("[deliver] listOrgAdminIds orgId {} Error; e : ", orgId, e);
            return new ArrayList<>();
        }
    }

    public List<UserDto> responseToUserDTOList(ListUsersByFilterResponse response) {
        List<UserDto> userDtoList = new ArrayList<>();
        List<User> users = response.getUsersList();
        if (!CollectionUtils.isEmpty(users)) {
            for (User user : users) {
                UserDto userDTO = deliverGrpcConvertMapper.toUserDto(user);
                if (Objects.nonNull(userDTO)) {
                    userDtoList.add(userDTO);
                }
            }
        }
        return userDtoList;
    }

    public UserDto responseToUserDTO(GetUserByIdResponse response) {
        User user = response.getUser();
        return deliverGrpcConvertMapper.toUserDto(user);
    }

    public boolean checkCurrentChecker(String userId, String orgId) {
        OrgInfoDto organization = this.getOrganization(orgId);
        // 判断当前用户是否是审核者
        AtomicBoolean isChecker = new AtomicBoolean(false);
        List<Role> roles = this.listRoleByOrgIdAndRoleName(orgId, "投放审核（系统）", SYSTEM);
        if (!CollectionUtils.isEmpty(roles)) {
            roles.stream().findFirst().ifPresent(role -> {
                List<UserRole> userRole = this.getUserRole(userId, role.getId());
                if (!org.apache.commons.collections4.CollectionUtils.isEmpty(userRole)) {
                    isChecker.set(true);
                }
            });
        }
        return isChecker.get() && organization.getIsDeliverCheck();
    }

    public List<OrgCustomSetting> listOrgCustomSetting(JSONObject paramJson) {
        ListOrgCustomSettingsRequest.Builder builder = ListOrgCustomSettingsRequest.newBuilder();

        OrgCustomSetting.Builder orgBuilder = OrgCustomSetting.newBuilder();
        if (StringUtils.isNotEmpty(paramJson.getString("orgId"))) {
            orgBuilder.setOrgId(paramJson.getString("orgId"));
        }
        if (paramJson.getBoolean("enable") != null) {
            orgBuilder.setEnable(paramJson.getBoolean("enable"));
        }
        if (StringUtils.isNotEmpty(paramJson.getString("domain"))) {
            orgBuilder.setDomain(paramJson.getString("domain"));
        }
        if (StringUtils.isNotEmpty(paramJson.getString("favicon"))) {
            orgBuilder.setFavicon(paramJson.getString("favicon"));
        }
        try {
            ListOrgCustomSettingsResponse response = orgCustomSettingServiceBlockingStub.listOrgCustomSettings(builder.buildPartial());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[deliver] listOrgCustomSetting Error; ErrorMsg: {}", response);
                return new ArrayList<>();
            }
            return response.getSettingsList();
        } catch (Exception e) {
            log.error("[deliver] USER listOrgCustomSetting Error; ErrorMsg: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    /**
     * 通过 root_group_id 获取该门店层级结构和子门店层级结构
     *
     * @param rootGroupId     root_group_id
     * @param includeInactive 是否包含失效节点
     * @return 层级结构
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/8/30 17:09
     */
    public GroupNode getGroupTreeByRootGroupId(String rootGroupId, boolean includeInactive) {
        GetGroupTreeByGroupIdRequest.Builder builder = GetGroupTreeByGroupIdRequest.newBuilder();
        builder.setGroupId(rootGroupId);
        builder.setIncludeInactive(includeInactive);
        try {
            GetGroupTreeByGroupIdResponse response = userGroupServiceBlockingStub.getGroupTreeByGroupId(builder.build());
            if (Objects.isNull(response) || Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Deliver] USER getGroupTreeByRootGroupId {}-{} Error; ErrorMsg: {}", rootGroupId, includeInactive, response);
                return null;
            }
            return response.getTree();
        } catch (Exception e) {
            log.error("[Deliver] USER getGroupTreeByRootGroupId {}-{} Error; ErrorMsg: {}", rootGroupId, includeInactive, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 获取单个GroupLevel
     *
     * @param groupLevelId 成员组层级id
     * @return 成员组层级DTO
     * @author <yuming.pan@idiaoyan.com>
     * @date 11:22 2021/8/27
     */
    public GroupLevel getGroupLevel(String groupLevelId) {
        GetGroupLevelByIdRequest.Builder builder = GetGroupLevelByIdRequest.newBuilder();
        builder.setLevelId(groupLevelId);
        try {
            GetGroupLevelByIdResponse response = userGroupServiceBlockingStub.getGroupLevelById(builder.build());
            if (Objects.isNull(response) || Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Deliver] USER getGroupLevel {} Error; ErrorMsg: {}", groupLevelId, response);
                return null;
            }
            return response.getLevel();
        } catch (Exception e) {
            log.error("[Deliver] USER getGroupLevel {} Error; ErrorMsg: {}", groupLevelId, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据邮箱ID获取邮箱
     *
     * @param smtpId
     */
    public Smtp getUserSmtpById(String smtpId) {
        GetSmtpByIdRequest.Builder builder = GetSmtpByIdRequest.newBuilder();
        builder.setId(smtpId);
        try {
            GetSmtpByIdResponse response = smtpServiceBlockingStub.getSmtpById(builder.build());
            if (Objects.isNull(response) || Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Deliver] USER getSmtpById {} Error; ErrorMsg: {}", smtpId, response);
                return null;
            }
            return response.getSmtp();
        } catch (Exception e) {
            log.error("[Deliver] USER getSmtpById {} Error;", smtpId, e);
            return null;
        }
    }

    /**
     * 通过公司id获取公司版本信息
     *
     * @param orgId 公司id
     */
    /*public Integer getOrgPackageEdition(String orgId) {
        GetOrgPackageEditionRequest.Builder builder = GetOrgPackageEditionRequest.newBuilder();
        builder.setId(orgId);
        try {
            GetOrgPackageEditionResponse response = orgServiceBlockingStub.getOrgPackageEdition(builder.build());
            if (Objects.isNull(response) || Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Deliver] USER getOrgPackageEdition {} Error; ErrorMsg: {}", orgId, response);
                return null;
            }
            return response.getPackageEdition().getNumber();
        } catch (Exception e) {
            log.error("[Deliver] USER getOrgPackageEdition {} Error;", orgId, e);
            return null;
        }
    }*/
    public List<CheckUserInfo> getCheckers(String orgId) {
        GetAuditRequest.Builder builder = GetAuditRequest.newBuilder();
        builder.setOrgId(orgId);
        try {
            GetAuditResponse response = userServiceBlockingStub.getAuditor(builder.build());
            if (Objects.isNull(response) || response.getStatus().getCodeValue() != 0) {
                log.error("[QDE] USER getCheckers Error; ErrorMsg: {}", response);
                return new ArrayList<>();
            }
            return response.getCheckUsersList();
        } catch (Exception e) {
            log.error("[QDE] USER getCheckers {} Error; ErrorMsg: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }
}
